Skip to content

fix: scope calendar progressive day-loader to caller date range#228

Merged
chubes4 merged 1 commit intomainfrom
fix-calendar-day-loader
May 4, 2026
Merged

fix: scope calendar progressive day-loader to caller date range#228
chubes4 merged 1 commit intomainfrom
fix-calendar-day-loader

Conversation

@chubes4
Copy link
Copy Markdown
Member

@chubes4 chubes4 commented May 4, 2026

Fixes #227.

Summary

The /wp-json/datamachine/v1/events/calendar endpoint ignored date_start / date_end for pagination boundaries. When the frontend day-loader fetched a single deferred day, it got back the full 5-day calendar page and injected the wrong day's events under every deferred shell. User-visible symptom on https://events.extrachill.com: events from May 3 appeared duplicated under May 4, May 5, May 6, and May 7. Same on every location archive (e.g. Charleston with geo filter).

Root cause (3 cooperating bugs from #227)

  1. compute_unique_event_dates() ignored the caller's date range — built SQL only from show_past, taxonomy, and geo, so unique_dates was always the full upcoming universe.
  2. PageBoundary::get_date_boundaries_for_page() returned canonical "page 1" boundaries (May 3..May 7) regardless of what the caller asked for, and the progressive branch then overwrote query_params['date_start'] / ['date_end'] to page_dates[0] (May 3). The actual event query returned May 3 events, the renderer emitted 5 date groups, and the counter said "Viewing May 3 - May 7" for a single-day request.
  3. day-loader.ts::injectDayHtml() picked the first .data-machine-events-wrapper out of the response via querySelector. Even with the backend fixed, this would happily inject the wrong day if a response ever contained multiple wrappers.

Fix

Backend — inc/Abilities/CalendarAbilities.php::executeGetCalendarPage()

When user_date_range is true (caller passed an explicit date_start and/or date_end):

  • Honor the caller's range as authoritative query_params['date_start'] / ['date_end'].
  • Skip pagination boundary computation and the progressive branch entirely (the day-loader is already asking for a single day; nothing to defer).
  • Filter events_per_date and recompute total_event_count to only include dates inside the requested range, so the counter and pagination metadata reflect what was actually asked for.
  • Set date_boundaries to the caller's range with max_pages = 1.

When user_date_range is false, behavior is unchanged: pagination + progressive deferral on page 1 still produce the full 5-day spread on first paint of the homepage / archives.

Frontend — inc/Blocks/Calendar/src/modules/day-loader.ts::injectDayHtml()

Scope the source wrapper lookup to the matching date group (defensive against backend regressions):

const date = getDateFromWrapper( wrapper );
const sourceWrapper = date
    ? temp.querySelector(
            `.data-machine-date-group[data-date="${ date }"] .data-machine-events-wrapper`
      ) || temp.querySelector( '.data-machine-events-wrapper' )
    : temp.querySelector( '.data-machine-events-wrapper' );

Before / after

curl -s "https://events.extrachill.com/wp-json/datamachine/v1/events/calendar?date_start=2026-05-04&date_end=2026-05-04" \
  | jq -r '.html' | grep -oE 'data-date="[^"]+"' | head

Before: 5 date groups (May 3, 4, 5, 6, 7), all events inside the May 3 group, the others empty/deferred. Counter: "Viewing May 3 - May 7 (500 of 31783 Events)".

After: one date group (May 4), only events whose start falls on May 4 (with late-night cutoff applied). Counter scoped to the requested range.

Validation

  • php -l inc/Abilities/CalendarAbilities.php — no syntax errors.
  • homeboy lint data-machine-events --path <worktree> --changed-since origin/main — PHPCS findings on my changed file reduced to only the 4 pre-existing findings (lines 376, 478, 479, 666). PHPStan passed. The 15 ESLint findings on day-loader.ts are pre-existing JSDoc/dependency-group warnings on lines I didn't touch.
  • npm run build in inc/Blocks/Calendar — webpack compiled successfully (74.7 KiB frontend bundle). Build artifacts are gitignored per repo convention; the deploy pipeline / homeboy build produces them.
  • Manual trace through ?date_start=2026-05-04&date_end=2026-05-04 confirms the new branch sets query_params['date_start'] / ['date_end'] to 2026-05-04, filters events_per_date to May 4 only, sets date_boundaries to May 4..May 4 with max_pages = 1, and skips the progressive branch entirely.
  • Non-progressive page-1 path (homepage first paint) is in the else branch and is functionally unchanged: same PageBoundary call, same range_start / range_end logic, same progressive-deferral kick-in for pages with ≥ PROGRESSIVE_THRESHOLD events.

cc <@532385681268408341>

When a caller passes explicit date_start/date_end to the calendar REST
endpoint (the progressive day-loader's per-day fetch), CalendarAbilities
ignored the caller's range for pagination boundaries. compute_unique_event_dates()
built SQL without applying date_start/date_end, then PageBoundary returned
"page 1" boundaries (e.g. May 3..May 7), and the progressive branch rewrote
query_params['date_start']/'date_end'] to page_dates[0] (May 3). The actual
event query returned May 3 events, the renderer emitted 5 date groups, and
the frontend day-loader picked the first .data-machine-events-wrapper out
of the response and injected May 3's events under May 4, May 5, May 6, May 7.

Backend: when user_date_range is true, honor the caller's range as authoritative,
skip pagination boundary computation and the progressive branch entirely,
and scope events_per_date / total_event_count / date_boundaries to the
requested range so the counter and pagination metadata reflect what was
asked for. Non-progressive page-1 path is unchanged.

Frontend: scope the wrapper lookup in injectDayHtml() to
.data-machine-date-group[data-date="$date"] so the wrong day's wrapper
can never be injected even if the backend regresses.
@chubes4
Copy link
Copy Markdown
Member Author

chubes4 commented May 4, 2026

Ready for review <@532385681268408341>

@homeboy-ci
Copy link
Copy Markdown
Contributor

homeboy-ci Bot commented May 4, 2026

Homeboy Results — data-machine-events

Audit

audit — passed

  • requested_detectors — 2 finding(s)
  • intra-method-duplication — 1 finding(s)
  • test_coverage — 1 finding(s)
  • Total: 4 finding(s)

Deep dive: homeboy audit data-machine-events --changed-since 8cf5c13

Tooling versions
  • Homeboy CLI: homeboy 0.156.1+f73327c
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: 52a3fd1
  • Action: Extra-Chill/homeboy-action@v2

@chubes4 chubes4 merged commit 1a32d48 into main May 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Calendar: progressive day-loader returns wrong day's events (date_start/date_end ignored on REST endpoint)

1 participant